home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Expert
/
Windows Expert.iso
/
windownt
/
wpj1_6.zip
/
EDITPRO.ZIP
/
EDITPRO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-30
|
25KB
|
623 lines
/* EditPro Version 1.00 Copyright (c) 1993 Eric Grass */
/* QuickCase:W KNB Version 1.00 */
#include "EDITPRO.h"
// Turn off some stuff to speed up compile time...
#define NORESOURCE TRUE
#define NOATOM TRUE
#define NOLANGUAGE TRUE
#define OEMRESOURCE TRUE
#define NORASTEROPS TRUE
#define NOMETAFILE TRUE
#define NOTEXTMETRIC TRUE
#define NOGDICAPMASKS TRUE
#define NODRAWTEXT TRUE
#define NOWH TRUE
#define NODEFERWINDOWPOS TRUE
#define NOCLIPBOARD TRUE
#define NOSYSMETRICS TRUE
#define NOSYSCOMMANDS TRUE
#define NOKANJI TRUE
#define NOSOUND TRUE
#define NOCOMM TRUE
#define NOPROFILER TRUE
char szFileName[256] = "*.*";
char szFileTitle[14];
WORD xoffset = 0, NoLines = 0, CurrentLineNo = 0;
WORD nTabStop = 8, TabStopLngth;
char szSpace[] = " ";
WORD textheight = 0, spacewidth = 0;
RECT rect;
HANDLE hFirstLine, hCurrentLine, hCurrentFont;
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
/***********************************************************************/
/* HANDLE hInstance; handle for this instance */
/* HANDLE hPrevInstance; handle for possible previous instances */
/* LPSTR lpszCmdLine; long pointer to exec command line */
/* int nCmdShow; Show code for main window display */
/***********************************************************************/
MSG msg; /* MSG structure to store your messages */
int nRc; /* return value from Register Classes */
strcpy(szAppName, "EDITPRO");
hInst = hInstance;
if(!hPrevInstance)
{
/* register window classes if first instance of application */
if ((nRc = nCwRegisterClasses()) == -1)
{
/* registering one of the windows failed */
LoadString(hInst, IDS_ERR_REGISTER_CLASS, szString, sizeof(szString));
MessageBox(NULL, szString, NULL, MB_ICONEXCLAMATION);
return nRc;
}
}
/* create application's Main window */
hWndMain = CreateWindow(
szAppName, /* Window class name */
"EditPro", /* Window's title */
WS_CAPTION | /* Title and Min/Max */
WS_SYSMENU | /* Add system menu box */
WS_MINIMIZEBOX | /* Add minimize box */
WS_MAXIMIZEBOX | /* Add maximize box */
WS_THICKFRAME | /* thick sizeable frame */
WS_VSCROLL | /* add vertical scroll bar */
WS_HSCROLL | /* add horizontal scroll bar */
WS_CLIPCHILDREN | /* don't draw in child windows areas */
WS_OVERLAPPED,
CW_USEDEFAULT, 0, /* Use default X, Y */
CW_USEDEFAULT, 0, /* Use default X, Y */
NULL, /* Parent window's handle */
NULL, /* Default to Class Menu */
hInst, /* Instance of window */
NULL); /* Create struct for WM_CREATE */
if(hWndMain == NULL)
{
LoadString(hInst, IDS_ERR_CREATE_WINDOW, szString, sizeof(szString));
MessageBox(NULL, szString, NULL, MB_ICONEXCLAMATION);
return IDS_ERR_CREATE_WINDOW;
}
ShowWindow(hWndMain, nCmdShow); /* display main window */
hAccel = LoadAccelerators(hInst, szAppName);
while(GetMessage(&msg, NULL, 0, 0)) /* Until WM_QUIT message */
{
if(TranslateAccelerator(hWndMain, hAccel, &msg))
continue;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/* Do clean up before exiting from the application */
CwUnRegisterClasses();
return msg.wParam;
} /* End of WinMain */
/************************************************************************/
/* */
/* Main Window Procedure */
/* */
/* This procedure provides service routines for the Windows events */
/* (messages) that Windows sends to the window, as well as the user */
/* initiated events (messages) that are generated when the user selects */
/* the action bar and pulldown menu controls or the corresponding */
/* keyboard accelerators. */
/* */
/************************************************************************/
LONG FAR PASCAL WndProc(HWND hWnd, WORD Message, WORD wParam, LONG lParam)
{
HMENU hMenu=0; /* handle for the menu */
HBITMAP hBitmap=0; /* handle for bitmaps */
HDC hDC; /* handle for the display device */
PAINTSTRUCT ps; /* holds PAINT information */
int nRc=0; /* return code */
WORD CurrentLine, hTemp, hTemp2, j, i, hFile, hTemp3, hOldCursor;
LPSTR lpLine, lpstrTemp;
DWORD dwTemp;
OFSTRUCT ofs;
switch (Message)
{
case WM_COMMAND:
/* The Windows messages for action bar and pulldown menu items */
/* are processed here. */
switch (wParam)
{
case IDM_F_OPENT:
if( hFirstLine) // If a file is already loaded, free it's memory...
SendMessage( hWnd, WM_COMMAND, IDM_F_CLOSE, NULL);
hOldCursor = SetCursor( LoadCursor( NULL, IDC_WAIT));
FileRoutine();
if( ( hFile = OpenFile( szFileName, &ofs, OF_PROMPT | OF_READ)) != -1)
{ if( (unsigned long)( dwTemp = _llseek( hFile, 0, 2)) > 0x00003FFFL)
dwTemp = 0x00003FFFL;
// Store the original buffer size in hDC.
hDC = (WORD) dwTemp;
_llseek( hFile, 0, 0);
if( !( lpstrTemp = GlobalLock( hTemp = GlobalAlloc( GMEM_MOVEABLE, dwTemp))))
CANTMAKEBUFF: { CreateMsgBox( hWnd, IDS_ERR_FILE2BIG);
_lclose( hFile);
PostMessage( hWnd, WM_CLOSE, hFirstLine = hCurrentLine = NULL, NULL);
return 0L;
}
if( !( lpLine = (LPSTR) GlobalLock( hTemp2 = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE, LINELNGTH))))
{ CreateMsgBox( hWnd, IDS_ERR_FILE2BIG);
GlobalUnlock( hTemp);
GlobalFree( hTemp);
_lclose( hFile);
hFirstLine = hCurrentLine = 0;
return 0L;
}
CurrentLine = 1;
hFirstLine = hCurrentLine = hTemp2;
(WORD) lpLine += FIRSTCHAR; // skip first four bytes & copy up to carriage return
hTemp3 = NULL;
// While not at End Of File, read the file into the buffer...
READFILE: _asm
{ MOV AH, 3FH
MOV BX, hFile
MOV CX, WORD PTR hDC // = Buffer Size
MOV DX, WORD PTR lpstrTemp
PUSH DS
MOV DS, WORD PTR lpstrTemp+2
CALL DOS3Call
POP DS
JNC READOKAY // Error
JMP STOPREADING
READOKAY: OR AX, AX
JNZ NOTTHEREYET
JMP STOPREADING // End Of File
NOTTHEREYET: MOV WORD PTR dwTemp, AX // = Actual # of bytes read
MOV WORD PTR dwTemp+2, 0
}
// While not at End of Buffer...
while( (WORD) lpstrTemp < (WORD) dwTemp)
{ if( (WORD) lpLine == LINELNGTH)
{ OkayMessageBoxf( hWnd, "Line %d is too long and will be truncated.", CurrentLine);
(WORD) lpLine = 2;
// Find next carriage return
while( (WORD) lpstrTemp < (WORD) dwTemp && (char) *lpstrTemp != '\r')
++((WORD)lpstrTemp);
}
if( (WORD) lpstrTemp < (WORD) dwTemp)
{ if( (char) *lpstrTemp == '\r') // if carriage return found,
{ if( (WORD) ++lpstrTemp < (WORD) dwTemp && (char) *lpstrTemp == '\n')
++((WORD) lpstrTemp); // discard the extra chars on the line
// Save the length of the line
_asm MOV ES, WORD PTR lpLine+2
_asm MOV AX, WORD PTR lpLine
_asm DEC AX
_asm MOV BYTE PTR ES:[FIRSTCHAR-1], AL
// Reallocate the line to minimum size...
if( !GlobalReAlloc( hTemp2, (DWORD)((WORD) lpLine), GMEM_MOVEABLE))
goto OUTOFMEM;
hTemp3 = hTemp2; // save previous line handle & allocate a new line.
(WORD) lpLine = 2; // /
if( !( lpLine = (LPSTR) GlobalLock( (WORD) *lpLine = hTemp2 = GlobalAlloc( GMEM_MOVEABLE, LINELNGTH))))
OUTOFMEM: { CreateMsgBox( hWnd, IDS_ERR_FILE2BIG);
GlobalUnlock( hTemp); // Unlock file buffer
GlobalFree( hTemp); // Free file buffer
GlobalUnlock( hTemp3);
_lclose( hFile);
PostMessage( hWnd, WM_CLOSE, NULL, NULL);
goto EMERGENCY;
}
GlobalUnlock( hTemp3);
_asm LES BX, lpLine
_asm MOV AX, hTemp3
_asm MOV WORD PTR ES:[BX], AX // Save previous line handle
_asm MOV WORD PTR ES:[BX+2], NULL // Set next line to NULL
(WORD) lpLine += FIRSTCHAR; // skip first FIRSTCHAR bytes
if( ++CurrentLine == 0x7FFF)
{ CreateMsgBox( hWnd, IDS_ERR_2MANYLINES);
goto STOPREADING;
}
} // else if carriage return missing, display message.
else
{ (char) *lpLine = (char) *lpstrTemp;
++((WORD) lpLine);
++((WORD) lpstrTemp);
}
}
} // END while()
// End of buffer was reached: reset lpstrTemp to beginning of buffer:
(WORD) lpstrTemp = 0;
goto READFILE; // Read next portion of file
STOPREADING: if( lpLine)
{ // Save the length of the line (a value from FIRSTCHAR-1 to LINELNGTH-1)
_asm MOV ES, WORD PTR lpLine+2
_asm MOV AX, WORD PTR lpLine
_asm DEC AX
_asm MOV BYTE PTR ES:[FIRSTCHAR-1], AL
// Set pointer to next line to NULL
_asm MOV WORD PTR ES:[2], NULL
// Reallocate the line to minimum size...
GlobalUnlock( hTemp2);
// if the handle is changed and previous line exists
// then we must save the new handle
GlobalReAlloc( hTemp2, (DWORD)((WORD) lpLine), GMEM_MOVEABLE);
}
FINITA: GlobalUnlock( hTemp);
GlobalFree( hTemp);
_lclose( hFile);
NoLines = CurrentLine;
SetScrollRange( hWnd, SB_VERT, 1, CurrentLine, TRUE);
}
EMERGENCY: SetCursor( hOldCursor);
// Display the file in the window
InvalidateRect( hWnd, NULL, TRUE);
UpdateWindow( hWnd);
break;
case IDM_F_CLOSE:
hTemp = hFirstLine;
while( hTemp) // Free all of the lines
{ if( lpLine = (LPSTR) GlobalLock( hTemp))
{ _asm LES BX, lpLine;
_asm MOV AX, WORD PTR ES:[BX+2]
_asm MOV hTemp2, AX
}
else
hTemp2 = NULL;
GlobalUnlock( hTemp);
GlobalFree( hTemp);
hTemp = hTemp2;
}
hFirstLine = hCurrentLine = NULL;
// Clear the window...
InvalidateRect( hWnd, NULL, TRUE);
UpdateWindow( hWnd);
/* Place User Code to respond to the */
/* Menu Item Named "&Close" here. */
break;
case IDM_F_EXITT:
/* Place User Code to respond to the */
/* Menu Item Named "E&xit\t" here. */
SendMessage( hWnd, WM_COMMAND, IDM_F_CLOSE, NULL);
PostMessage( hWnd, WM_CLOSE, NULL, NULL);
break;
case IDM_F_ABOUT:
/* Place User Code to respond to the */
/* Menu Item Named "&About..." here. */
{
FARPROC lpfnABOUTMsgProc;
lpfnABOUTMsgProc = MakeProcInstance((FARPROC)ABOUTMsgProc, hInst);
nRc = DialogBox(hInst, MAKEINTRESOURCE(100), hWnd, lpfnABOUTMsgProc);
FreeProcInstance(lpfnABOUTMsgProc);
}
break;
default:
return DefWindowProc(hWnd, Message, wParam, lParam);
}
break; /* End of WM_COMMAND */
case WM_CREATE:
SetScrollRange( hWnd, SB_HORZ, 0, 1024, TRUE);
hCurrentFont = GetStockObject( SYSTEM_FONT);
break; /* End of WM_CREATE */
case WM_MOVE: /* code for moving the window */
break;
case WM_SIZE: /* code for sizing client area */
GetClientRect( hWnd, &rect);
break; /* End of WM_SIZE */
case WM_PAINT: /* code for the window's client area */
/* Obtain a handle to the device context */
/* BeginPaint will sends WM_ERASEBKGND if appropriate */
hDC = BeginPaint(hWnd, &ps);
/* Included in case the background is not a pure color */
SetBkMode(hDC, TRANSPARENT);
hTemp3 = SelectObject( hDC, hCurrentFont);
_asm
{ PUSH hDC
PUSH DS
PUSH OFFSET szSpace // Points to space character
PUSH 1 // Number of chars. in string
CALL GetTextExtent
MOV textheight, DX // Get the space character height
MOV spacewidth, AX // Get the space character width
}
// Save the tab stop lenghth (in pixels)
TabStopLngth = nTabStop*spacewidth;
hTemp2 = hTemp = hCurrentLine;
CurrentLine = 0; // Holds the current Y-screen coordinate
// Start from top line and go to succesive lines until bottom of screen reached
hFile = ps.rcPaint.top - textheight;
while( hTemp && (signed) CurrentLine < ps.rcPaint.bottom)
{ if( lpLine = GlobalLock( hTemp2 = hTemp))
{ if( (signed) CurrentLine > (signed) hFile)
{ _asm
{ LES BX, lpLine
MOV AL, BYTE PTR ES:[BX+4]
XOR AH, AH
SUB AX, (FIRSTCHAR-1) // AX = nCount
JZ NODRAW
// The same as TabbedTextOut( hDC, xoffset, CurrentLine, (LPSTR) lpLine+FIRSTCHAR, nCount, 1, &TabStopLngth, xoffset);
PUSH hDC
PUSH xoffset // = X-coord
PUSH CurrentLine // = Y-coord.
PUSH ES // = lpString base
PUSH FIRSTCHAR // = lpString offset
PUSH AX // = nCount
PUSH 1 // = nTabPositions
PUSH DS // = lpTabStopPositions base
PUSH OFFSET TabStopLngth // = lpTabStopPositions offset
PUSH xoffset // = nTabOrigin
CALL TabbedTextOut
}
}
NODRAW: CurrentLine += textheight;
_asm LES BX, lpLine
_asm MOV AX, WORD PTR ES:[BX+2]
_asm MOV hTemp, AX
GlobalUnlock( hTemp2);
} // END if
else
hTemp = NULL;
} // END while
SelectObject( hDC, hTemp3); // Restore Previous Font
ValidateRect( hWnd, (LPRECT) NULL);
/* Inform Windows painting is complete */
EndPaint(hWnd, &ps);
break; /* End of WM_PAINT */
case WM_VSCROLL:
switch(wParam)
{
// Set new position to LastLine and update scroll bar
// (if shown), CB_CURRENTLINE, CBHMEM, MDI Child Window,
// and status bar.
case SB_LINEDOWN:
case SB_PAGEDOWN:
// Page down only if 2nd-to-last line isn't NULL
PAGEDOWN: hTemp2 = hTemp = hCurrentLine;
CurrentLine = 0; // Holds the current Y-screen coordinate
i = CurrentLineNo;
// Start from top line and go to succesive lines until bottom of screen reached
while( hTemp && (signed) CurrentLine < rect.bottom)
{ if( lpLine = GlobalLock( hTemp2 = hTemp))
{ CurrentLine += textheight;
_asm LES BX, lpLine
_asm MOV AX, WORD PTR ES:[BX+2]
_asm MOV hTemp, AX
_asm INC i
GlobalUnlock( hTemp2);
} // END if
else
hTemp = NULL;
} // END while
hCurrentLine = hTemp2;
CurrentLineNo = --i;
InvalidateRect( hWnd, NULL, TRUE);
UpdateWindow( hWnd);
SetScrollPos( hWnd, SB_VERT, i, TRUE);
break;
case SB_LINEUP:
case SB_PAGEUP:
PAGEUP: CurrentLine = 0; // Initialize line number & handle
hTemp2 = hTemp = hCurrentLine;
i = CurrentLineNo;
// Start at bottom and go to preceeding lines until top of screen reached
while( hTemp && (signed) CurrentLine < rect.bottom)
{ if( lpLine = GlobalLock( hTemp2 = hTemp))
{ CurrentLine += textheight;
// Fetch preceding line
_asm LES BX, lpLine
_asm MOV AX, WORD PTR ES:[BX]
_asm MOV hTemp, AX
_asm DEC WORD PTR i
GlobalUnlock( hTemp2);
}
else
hTemp = NULL;
}
hCurrentLine = hTemp2;
SetScrollPos( hWnd, SB_VERT, ++i, TRUE);
CurrentLineNo = i;
InvalidateRect( hWnd, &rect, TRUE);
UpdateWindow( hWnd);
break;
default:
return FALSE;
}
break;
case WM_HSCROLL:
switch (wParam)
{
case SB_PAGEDOWN:
case SB_LINEDOWN: // Scroll to the right
xoffset = xoffset - TabStopLngth;
SetScrollPos( hWnd, SB_HORZ, -xoffset, TRUE);
ScrollWindow( hWnd, -TabStopLngth, 0, NULL, NULL);
UpdateWindow( hWnd);
break;
case SB_PAGEUP:
case SB_LINEUP: // Scroll to the left
if( (signed) ( j = xoffset + TabStopLngth) > (signed) 0)
break;
SetScrollPos( hWnd, SB_HORZ, -(xoffset = j), TRUE);
ScrollWindow( hWnd, TabStopLngth, 0, NULL, NULL);
UpdateWindow( hWnd);
break;
default:
return FALSE;
}
break;
case WM_CLOSE: /* close the window */
/* Destroy child windows, modeless dialogs, then, this window */
CLOSE: DestroyWindow(hWnd);
if (hWnd == hWndMain)
PostQuitMessage(0); /* Quit the application */
break;
default:
/* For any message for which you don't specifically provide a */
/* service routine, you should return the message to Windows */
/* for default message processing. */
return DefWindowProc(hWnd, Message, wParam, lParam);
}
return 0L;
} /* End of WndProc */
/************************************************************************/
/* */
/* Dialog Window Procedure */
/* */
/* This procedure is associated with the dialog box that is included in */
/* the function name of the procedure. It provides the service routines */
/* for the events (messages) that occur because the end user operates */
/* one of the dialog box's buttons, entry fields, or controls. */
/* */
/************************************************************************/
BOOL FAR PASCAL ABOUTMsgProc(HWND hWndDlg, WORD Message, WORD wParam, LONG lParam)
{
switch(Message)
{
case WM_INITDIALOG:
cwCenter(hWndDlg, 0);
/* initialize working variables */
break; /* End of WM_INITDIALOG */
case WM_CLOSE:
/* Closing the Dialog behaves the same as Cancel */
PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L);
break; /* End of WM_CLOSE */
case WM_COMMAND:
switch(wParam)
{
case IDCANCEL:
case IDOK:
/* Ignore data values entered into the controls */
/* and dismiss the dialog window returning FALSE */
EndDialog(hWndDlg, FALSE);
break;
}
break; /* End of WM_COMMAND */
default:
return FALSE;
}
return TRUE;
} /* End of ABOUTMsgProc */
/************************************************************************/
/* */
/* nCwRegisterClasses Function */
/* */
/* The following function registers all the classes of all the windows */
/* associated with this application. The function returns an error code */
/* if unsuccessful, otherwise it returns 0. */
/* */
/************************************************************************/
int nCwRegisterClasses(void)
{
WNDCLASS wndclass; /* struct to define a window class */
memset(&wndclass, 0x00, sizeof(WNDCLASS));
/* load WNDCLASS with window's characteristics */
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW;
wndclass.lpfnWndProc = WndProc;
/* Extra storage for Class and Window objects */
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInst;
wndclass.hIcon = LoadIcon(hInst, "EDITPRO");
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
/* Create brush for erasing background */
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclass.lpszMenuName = szAppName; /* Menu Name is App Name */
wndclass.lpszClassName = szAppName; /* Class Name is App Name */
if(!RegisterClass(&wndclass))
return -1;
return(0);
} /* End of nCwRegisterClasses */
/************************************************************************/
/* cwCenter Function */
/* */
/* centers a window based on the client area of its parent */
/* */
/************************************************************************/
void cwCenter(hWnd, top)
HWND hWnd;
int top;
{
POINT pt;
RECT swp;
RECT rParent;
int iwidth;
int iheight;
/* get the rectangles for the parent and the child */
GetWindowRect(hWnd, &swp);
GetClientRect(hWndMain, &rParent);
/* calculate the height and width for MoveWindow */
iwidth = swp.right - swp.left;
iheight = swp.bottom - swp.top;
/* find the center point and convert to screen coordinates */
pt.x = (rParent.right - rParent.left) / 2;
pt.y = (rParent.bottom - rParent.top) / 2;
ClientToScreen(hWndMain, &pt);
/* calculate the new x, y starting point */
pt.x = pt.x - (iwidth / 2);
pt.y = pt.y - (iheight / 2);
/* top will adjust the window position, up or down */
if(top)
pt.y = pt.y + top;
/* move the window */
MoveWindow(hWnd, pt.x, pt.y, iwidth, iheight, FALSE);
}
/************************************************************************/
/* CwUnRegisterClasses Function */
/* */
/* Deletes any refrences to windows resources created for this */
/* application, frees memory, deletes instance, handles and does */
/* clean up prior to exiting the window */
/* */
/************************************************************************/
void CwUnRegisterClasses(void)
{
WNDCLASS wndclass; /* struct to define a window class */
memset(&wndclass, 0x00, sizeof(WNDCLASS));
UnregisterClass(szAppName, hInst);
} /* End of CwUnRegisterClasses */